import { actionDebounce, toPage } from '@/utils/mpHelper'
import type { OTAHelper, OTAHelperConfigOptions } from './types'
import type { WS } from '@/utils/socket/types'
import { WebsocketManager } from '@/utils/socket/WebsocketManager'
import { getAllSetting, type ApplianceSetting } from '@/api/appliance'
import { getFirmwareVersion, upgradeCombinationFirmware, type FirmwareVersionType } from '@/api/biwd'
import { UPGRADE_MCUSTATUS } from '@/constants/WDCommand'
import { useWebsocketListener } from '@/utils/socket/WebSocketHandlerImp'
import { SuccessModalAcknowledge } from '@/constants/UniEventKeys'
import i18n from '@/i18n'
type UpgradeCommand = {
  wifi?: UpgradeCommandValue
  mcu?: UpgradeCommandValue
}
type UpgradeCommandValue = {
  url: string
  pid: string
  hwcode: string
  version: string
}

export default class BiwdOtaHelper implements OTAHelper {
  configOptions!: OTAHelperConfigOptions

  upgradingModalVisible = ref(false) // 是否显示【固件升级中】弹框
  successModalVisible = ref(false) // 是否显示【固件已升级至最新版本】确认框
  retryModalVisible = ref(false) // 是否显示【网络异常，请重试】弹框
  upgradeDetected = ref(false) // 是否检测到升级
  upgradingMessage = ref('')

  private mcuStatus = ref(0)
  private upgradeType = ref('')
  private upgradeNum = ref(0)
  private upgradeCommand = ref<UpgradeCommand>({})
  private upgradeTwo = ref(false)
  private vib = ref('')
  private isBIWDValueVib = computed(() =>
    ['WS5054BB1C', 'WS5053BB1C', 'WS5053BC1C', 'WS5054BC1C', 'WBB6050B1C', 'WBB6050C1C'].includes(this.vib.value)
  )

  constructor(options: OTAHelperConfigOptions) {
    this.configOptions = options
    this.vib.value = options?.vib
    this.addMessageListener()
    this.initBindings(options.scene as string)
  }

  destroy(): void {
    this.removeMessageListener()
  }

  get haId() {
    return this.configOptions.haId
  }

  async checkRemoteUpgradeSupported() {}
  async acknowledgeSuccessful() {
    uni.$emit(SuccessModalAcknowledge)
  }

  async toUpgradePage() {
    const options = this.configOptions
    await toPage('/pages/appliance/settings/ota/firmwareUpdate', {
      brand: options.brand,
      type: options.type,
      vib: options.vib,
      haId: options.haId,
    })
  }
  hideAllModal() {
    this.upgradingModalVisible.value = false
    this.successModalVisible.value = false
    this.retryModalVisible.value = false
  }
  checkUpgrade = actionDebounce({
    call: async () => {
      if (!this.isBIWDValueVib.value) return
      if (this.configOptions.scene === 'firmware') {
        const settingRes = await getAllSetting(this.haId)
        const { settings } = settingRes.data || []
        this.getInitMcuStatus(settings)
      }

      const versionRes = await getFirmwareVersion(this.haId)
      const versionList = versionRes.data || []
      this.getUpgradeVersion(versionList)
    },
  })
  private async getInitMcuStatus(settings: ApplianceSetting[]) {
    settings.forEach((item) => {
      if (item.key === UPGRADE_MCUSTATUS) {
        this.mcuStatus.value = Number(item.value)
      }
    })
  }
  private async getUpgradeVersion(versionList: FirmwareVersionType[], type?: string) {
    const commands: UpgradeCommand = {}
    let hasUpgrade = false
    let upgradeVersionNull = false // 只要云端布置版本为空将不可升级
    versionList.forEach((item) => {
      // 正在升级中
      if (item.upgradingVersion !== '' && item.upgradingVersion !== '0') {
        this.successModalVisible.value = false
        this.retryModalVisible.value = false
        this.upgradingModalVisible.value = true
        this.upgradeType.value = item.hwcode === '56' ? 'Wifi' : 'MCU'
      }
      if (!item.serverVersion.version) {
        upgradeVersionNull = true
        return
      }
      // 需要升级获取升级指令
      const versionHasUpgrade = Number(item.version) !== Number(item.serverVersion.version)
      if (versionHasUpgrade) {
        hasUpgrade = true
      }
      if (versionHasUpgrade && type !== 'check') {
        this.upgradeNum.value++
        if (item.hwcode === '56') {
          commands.wifi = {
            url: item.serverVersion.url,
            pid: item.pid,
            hwcode: item.hwcode,
            version: item.serverVersion.version,
          }
        } else {
          commands.mcu = {
            url: item.serverVersion.url,
            pid: item.pid,
            hwcode: item.hwcode,
            version: item.serverVersion.version,
          }
        }
      }
    })
    if (upgradeVersionNull) return
    if (this.upgradeNum.value === 2) this.upgradeTwo.value = true
    this.upgradeDetected.value = hasUpgrade
    this.upgradeCommand.value = commands
  }
  allowUpgrade = actionDebounce({
    call: async () => {
      if (Object.keys(this.upgradeCommand.value).length === 0) return
      const res = await upgradeCombinationFirmware(this.haId, this.upgradeCommand.value)

      if (res.code !== 0) {
        this.retryModalVisible.value = true
      } else {
        this.upgradeType.value === 'Wifi'
        this.upgradingModalVisible.value = true
      }
    },
  })
  private messageListener = (msg: WS.Message) => {
    if (msg.haId !== this.haId || !Array.isArray(msg.items)) return
    msg.items.forEach((item) => {
      if (item.key === UPGRADE_MCUSTATUS) {
        this.mcuStatus.value = Number(item.value)
      }
    })
  }
  private addMessageListener(): void {
    useWebsocketListener(WebsocketManager.instance.oemWebsocket, this.messageListener)
  }
  private removeMessageListener(): void {
    WebsocketManager.instance.oemWebsocket.removeMessageListener(this.messageListener)
  }
  private initBindings(scene: string): void {
    watchEffect(async () => {
      switch (this.mcuStatus.value) {
        case MCUStatus.Normal:
          if (!this.upgradeTwo.value) {
            this.upgradingModalVisible.value = false
          }
          this.upgradingMessage.value = ''
          break
        case MCUStatus.Downloading:
          if (scene !== 'firmware') return
          const res = await getFirmwareVersion(this.haId)
          const versionList = res.data || []
          this.getUpgradeVersion(versionList, 'check')
          this.retryModalVisible.value = false
          this.successModalVisible.value = false
          this.upgradingMessage.value =
            this.upgradeType.value === 'Wifi' ? '正在下载固件升级包...' : '正在下载MCU升级包...'
          this.upgradingModalVisible.value = true
          break
        case MCUStatus.Transfering:
          if (scene !== 'firmware') return
          this.retryModalVisible.value = false
          this.successModalVisible.value = false
          this.upgradingMessage.value =
            this.upgradeType.value === 'Wifi' ? '正在传输固件升级包...' : '正在传输MCU升级包...'
          this.upgradingModalVisible.value = true
          break
        case MCUStatus.Restart:
          if (scene !== 'firmware') return
          this.retryModalVisible.value = false
          this.successModalVisible.value = false
          this.upgradingMessage.value = this.upgradeType.value === 'Wifi' ? '正在重启通信模组...' : '正在重启家电...'
          this.upgradingModalVisible.value = true
          break
        case MCUStatus.UpdateSuccess:
          if (this.upgradeNum.value !== 2) {
            this.upgradingModalVisible.value = false
            this.retryModalVisible.value = false
            this.upgradingMessage.value = ''
            if (scene === 'firmware') {
              uni.showToast({
                title: i18n.global.t('Appliance.Settings.FirmwareUpgrade.UpgradeSucess.Toast.Title'),
                icon: 'success',
              })
              uni.$emit(SuccessModalAcknowledge)
            } else {
              this.successModalVisible.value = true
            }
            this.upgradeDetected.value = false
          } else {
            this.upgradeNum.value--
            if (scene === 'firmware') {
              this.upgradingModalVisible.value = true
            }
          }
          break
        case MCUStatus.UpdateFail:
          if (scene !== 'firmware') return
          this.successModalVisible.value = false
          this.upgradingModalVisible.value = false
          this.retryModalVisible.value = true
          this.upgradingMessage.value = ''
          break
        default:
          break
      }
    })
  }
}

export enum MCUStatus {
  Normal = 0,
  Downloading = 1,
  Transfering = 2,
  Restart = 3,
  UpdateSuccess = 4,
  UpdateFail = 5,
}
